package com.tianji.learning.service.impl;

import cn.hutool.db.DbRuntimeException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CategoryClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.StringUtils;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.service.IAdminInteractionQuestionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class IAdminInteractionQuestionServiceImpl implements IAdminInteractionQuestionService {
    private final InteractionQuestionMapper questionMapper;
    private final SearchClient searchClient;
    private final UserClient userClient;
    private final CourseClient courseClient;
    private final CategoryCache categoryCache;
    private final CatalogueClient catalogueClient;

    /**
     * 管理端分页查询问题列表
     *
     * @param page
     * @return
     */
    @Override
    public PageDTO<QuestionAdminVO> pageQueryQuestion(QuestionAdminPageQuery page) {
        //1、已知课程名称 从es中查询课程id的集合
        List<Long> idList = null;
        if (StringUtils.isNotEmpty(page.getCourseName())) {
            idList = searchClient.queryCoursesIdByName(page.getCourseName());

        }
        //2、对互动问题进行分页查询 需要课程id的集合
        Page<InteractionQuestion> questionPage = questionMapper.selectPage(page.toMpPageDefaultSortByCreateTimeDesc(), new LambdaQueryWrapper<InteractionQuestion>().eq(page.getStatus() != null, InteractionQuestion::getStatus, page.getStatus()).gt(page.getBeginTime() != null, InteractionQuestion::getCreateTime, page.getBeginTime()).lt(page.getEndTime() != null, InteractionQuestion::getCreateTime, page.getEndTime()).in(idList != null, InteractionQuestion::getCourseId, idList));
        List<InteractionQuestion> records = questionPage.getRecords();
        if (CollUtils.isEmpty(records)) {
            return PageDTO.empty(questionPage);
        }
        //3、对于QuestionAdminVO中InteractionQuestion一些字段是缺少的
        //3.0 查找之前将用户id 课程id 章节id分别放入set集合之中
        Set<Long> userIdList = new HashSet<>();
        Set<Long> courseIdList = new HashSet<>();
        Set<Long> chapterIdList = new HashSet<>();
        for (InteractionQuestion record : records) {
            userIdList.add(record.getUserId());
            courseIdList.add(record.getCourseId());
            chapterIdList.add(record.getChapterId());
            chapterIdList.add(record.getSectionId());
        }
        //3.1 查找用户昵称
        List<UserDTO> userList = userClient.queryUserByIds(userIdList);
        if (CollUtils.isEmpty(userList)) {
            throw new BizIllegalException("用户不存在");
        }
        Map<Long, String> userId2Name = userList.stream().collect(Collectors.toMap(UserDTO::getId, UserDTO::getName));
        //3.2 查找课程名称
        List<CourseSimpleInfoDTO> infoList = courseClient.getSimpleInfoList(courseIdList);
        Map<Long, CourseSimpleInfoDTO> infoDTOMap = null;
        if (CollUtils.isNotEmpty(infoList)) {
            infoDTOMap = infoList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));
        }
        //3.3 查找章节名称
        List<CataSimpleInfoDTO> cataSimpleInfoDTOList = catalogueClient.batchQueryCatalogue(chapterIdList);
        Map<Long, String> categoryNameMap = null;
        if (CollUtils.isNotEmpty(cataSimpleInfoDTOList)) {
            categoryNameMap = cataSimpleInfoDTOList.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }
        //4、封装po到vo
        List<QuestionAdminVO> list = new ArrayList<>();
        for (InteractionQuestion record : records) {
            //先直接拷贝公共的属性
            QuestionAdminVO vo = BeanUtils.toBean(record, QuestionAdminVO.class);

            //给特定的属性进行赋值
            vo.setUserName(userId2Name.get(record.getUserId()));
            if (infoDTOMap != null) {
                vo.setCourseName(infoDTOMap.get(record.getCourseId()).getName());
                //课程分类名称拼接
                vo.setCategoryName(categoryCache.getCategoryNames(infoDTOMap.get(record.getCourseId()).getCategoryIds()));
            }
            if (categoryNameMap != null) {
                vo.setChapterName(categoryNameMap.get(record.getChapterId()));
                vo.setSectionName(categoryNameMap.get(record.getSectionId()));
            }

            list.add(vo);
        }
        return PageDTO.of(questionPage, list);
    }

    /**
     * 管理端根据id查询问题详情
     *
     * @param id
     * @return
     */
    @Override
    public QuestionAdminVO queryQuestionById(Long id) {
        //1、参数检验
        if (id == null) {
            throw new BizIllegalException("参数错误");
        }
        //2、查询问题表
        InteractionQuestion interactionQuestion = questionMapper.selectById(id);
        if (interactionQuestion == null) {
            throw new BizIllegalException("问题不存在");
        }

        //3、po转vo的时候需要补充的字段
        /**
         *     private String userName;
         *     private String teacherName;
         *     private String courseName;
         *     private String chapterName;
         *     private String sectionName;
         *     @ApiModelProperty("三级分类名称，中间使用/隔开")
         *     private String categoryName;
         */
        //3.1 根据课程id来获取课程负责教师的id 加入用户id 获取id和名称的映射
        //课程负责教师就是第一个
        List<Long> ids = courseClient.getTeacherId(interactionQuestion.getCourseId());
        ids.add(interactionQuestion.getUserId());
        List<UserDTO> userDTOS = userClient.queryUserByIds(ids);
        if (CollUtils.isEmpty(userDTOS)) {
            throw new BizIllegalException("用户不存在");
        }
        Map<Long, String> userMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, UserDTO::getName));

        //3.2 获取课程名称
        CourseFullInfoDTO courseInfo = courseClient.getCourseInfoById(interactionQuestion.getCourseId(), false, false);
        if (courseInfo == null) {
            throw new BizIllegalException("课程不存在");
        }

        //3.3 获取章节名称
        List<CataSimpleInfoDTO> cataSimpleInfoDTOList = catalogueClient.batchQueryCatalogue(CollUtils.newArrayList(interactionQuestion.getChapterId(), interactionQuestion.getSectionId()));
        if (CollUtils.isEmpty(cataSimpleInfoDTOList)) {
            throw new BizIllegalException("章节不存在");
        }
        Map<Long, String> categoryNameMap = cataSimpleInfoDTOList.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));

        //4、进行po到vo的转换
        QuestionAdminVO questionAdminVO = BeanUtils.copyBean(interactionQuestion, QuestionAdminVO.class);
        questionAdminVO.setUserName(userMap.get(interactionQuestion.getUserId()));
        if (ids.size() > 1) {
            questionAdminVO.setTeacherName(userMap.get(ids.get(0)));
        }
        questionAdminVO.setCourseName(courseInfo.getName());
        questionAdminVO.setCategoryName(categoryCache.getCategoryNames(courseInfo.getCategoryIds()));
        questionAdminVO.setChapterName(categoryNameMap.get(interactionQuestion.getChapterId()));
        questionAdminVO.setSectionName(categoryNameMap.get(interactionQuestion.getSectionId()));
        //5、更新status
        questionMapper.updateById(new InteractionQuestion().setId(id).setStatus(QuestionStatus.CHECKED));
        return questionAdminVO;
    }

    /**
     * 管理端修改问题状态
     * @param id
     * @param hidden
     */
    @Override
    @Transactional
    public void updateStatus(Long id, Boolean hidden) {
        int updateLine = questionMapper.updateById(new InteractionQuestion().setId(id).setHidden(hidden));
        if (updateLine <= 0){
            throw new DbRuntimeException("修改失败");
        }
    }
}
